package com.xpec.c4.db.basic;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.ProjectionList;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;

import com.ms.player.AgentData;
import com.ms.player.Player;
import com.xpec.c4.db.hibernate.manager.HibernateLogManager;
import com.xpec.c4.db.hibernate.manager.HibernateManager;
import com.xpec.c4.db.model.log.basic.BasicLogModel;
import com.xpec.c4.game.datamanager.agent.money.MoneyChangeWay;
import com.xpec.c4.game.utility.GUID;
import com.xpec.c4.game.utility.GameUtility;
import com.xpec.c4.service.module.BasicServiceModule;
import com.xpec.c4.service.module.datacenter.player.db.OpenScoreChangeWay;
import com.xpec.c4.service.module.datacenter.player.db.OpenScoreLogModel;
import com.xpec.c4.service.module.datacenter.player.db.PlayerMoneyChangeLogModel;
import com.xpec.c4.service.module.datacenter.player.db.PlayerTmpCashChangeLogModel;
import com.xpec.c4.service.module.datacenter.player.db.TmpCashChangeWay;

/**
 * LOG库的DAO
 * 
 * @author zhongzhengkai 2011-11-28
 */
public class BasicLogDAO {
	/** log4j object */
	private static final Log log = LogFactory.getLog(BasicLogDAO.class);

	/**
	 * 批量存储日志对象
	 * 
	 * @param logs
	 *            author: zhongzhengkai date: 2011 2011-11-28 上午11:13:57
	 */
	public static boolean saveLogs(List<? extends BasicLogModel> logs) {
		HibernateLogManager.txBegin();
		for (BasicLogModel log : logs) {
			save(log);
		}
		boolean success = HibernateLogManager
				.txCommitFailRollbackClearSession();
		return success;
	}

	/**
	 * 存储日志对象
	 * 
	 * @param log
	 * @return author: zhongzhengkai date: 2011 2011-12-6 下午04:34:27
	 */
	public static boolean saveLog(BasicLogModel log) {
		HibernateLogManager.txBegin();
		save(log);
		boolean success = HibernateLogManager
				.txCommitFailRollbackClearSession();
		return success;
	}

	/**
	 * 更新日志对象
	 * 
	 * @param log
	 * @return author: zhongzhengkai date: 2011 2011-12-6 下午04:33:16
	 */
	public static boolean updateLog(BasicLogModel log) {
		HibernateLogManager.txBegin();
		 update(log);
		boolean success = HibernateLogManager
				.txCommitFailRollbackClearSession();
		return success;
	}

	/**
	 * @param clazz
	 * @param parameters
	 * @return 删除的记录条数 author: zhongzhengkai date: 2011 2011-12-6 下午04:32:06
	 */
	public static int deleteLog(BasicLogModel log) {
		HibernateLogManager.txBegin();
		Class<? extends BasicLogModel> logClass = log.getClass();
		HashMap<String, Object> map = new HashMap<String, Object>();
			map.put("eventId",  log.getEventId());
			int i = delete(logClass, map);
			HibernateLogManager.txCommitFailRollbackClearSession();
			return i;
	}

	/**
	 * 存储日志对象
	 * 
	 * @param logs
	 *            author: zhongzhengkai date: 2011 2011-11-28 上午11:13:57
	 */
	public static BasicLogModel loadLog(String Db_id) {
		// BasicLogModel model=load(FirstLog.class,Db_id);
		// return model;
		if (Db_id == null) {
			return null;
		}
		Session session = HibernateLogManager.getSession();
		Criteria criteria = session.createCriteria(BasicLogModel.class);
		criteria.add(Restrictions.eq("db_id", Db_id));
		BasicLogModel model = (BasicLogModel) criteria.uniqueResult();
		HibernateManager.endSession();
		return model;
	}

	/**
	 * 保存实体对象
	 * 
	 * @param entity
	 *            待保存的实体对象
	 */
	public static void save(BasicLogModel entity) {
		if (entity == null) {
			return;
		}
		Session session = HibernateLogManager.getSession();
		session.save(entity);
	}

	/**
	 * 更新实体对象
	 * 
	 * @param entity
	 *            待更新的实体对象
	 */
	public static void update(BasicLogModel entity) {
		Session session = HibernateLogManager.getSession();
		session.update(entity);
	}

	/**
	 * 保存或更新实体对象
	 * 
	 * @param entity
	 *            待处理的实体对象
	 */
	public static void saveOrUpdate(BasicLogModel entity) {
		Session session = HibernateLogManager.getSession();
		session.saveOrUpdate(entity);
	}

	/**
	 * 删除实体对象
	 * 
	 * @param entity
	 *            待删除的实体对象
	 */
	public static void delete(BasicLogModel entity) {
		Session session = HibernateLogManager.getSession();
		session.delete(entity);
	}

	/**
	 * 从数据库读取指定的实体对象
	 * 
	 * @param clazz
	 * @param db_id
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T extends BasicLogModel> T get(Class<T> clazz,
			Serializable eventId) {
		Session session = HibernateLogManager.getSession();
		Object obj = session.get(clazz, eventId);
		return (T) obj;
	}

	/**
	 * 从数据库读取指定的实体对象
	 * 
	 * @param clazz
	 * @param db_id
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T extends BasicLogModel> T load(Class<T> clazz,
			Serializable eventId) {
		Session session = HibernateLogManager.getSession();
		Object obj = session.get(clazz, eventId);
		HibernateLogManager.endSession();
		return (T) obj;
	}

	/**
	 * 从数据库读取指定的实体对象
	 * 
	 * @param clazz
	 * @param db_id
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T extends BasicLogModel> List<T> loadAll(Class<T> clazz) {
		Session session = HibernateLogManager.getSession();
		Criteria cri = session.createCriteria(clazz);
		HibernateLogManager.endSession();
		return cri.list();
	}

	/**
	 * 执行指定的SQL语句
	 * 
	 * @param command
	 * @return
	 */
	public static int execute(String command) {
		Session session = HibernateLogManager.getSession();
		Query query = session.createSQLQuery(command);
		return query.executeUpdate();
	}

	/**
	 * LOG信息查询功能 修改成查询从数据库。
	 * 
	 * @param accountID
	 *            帐户ID
	 * @param firstResult
	 *            开始位置
	 * @param maxResults
	 *            记录长度
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T extends BasicLogModel> List<T> loadAndExpression(
			Class<T> clazz, HashMap<String, Object> parameters,
			int firstResult, int maxResults, String order) {
		Session session = HibernateLogManager.getSession();
		Criteria criteria = session.createCriteria(clazz);
		// 参数设置
		Set<String> keys = parameters.keySet();
		Object value;
		for (String key : keys) {
			value = parameters.get(key);
			if (key != null && value != null && value.toString().length() > 0) {
				criteria.add(Restrictions.eq(key, value));
			}
		}

		// 开始位置
		if (firstResult >= 0) {
			criteria.setFirstResult(firstResult);
		}

		// 记录长度
		if (maxResults >= 0) {
			criteria.setMaxResults(maxResults);
		}

		// 按时间排序
		criteria.addOrder(Order.asc(order));

		return criteria.list();
	}

	/**
	 * 查找符合条件的数据记录数量
	 * 
	 * @param clazz
	 *            操作的实体类
	 * @param parameters
	 *            参数
	 * @return
	 */
	public static Long getCountAndExpression(Class<? extends BasicLogModel> clazz,
			HashMap<String, Object> parameters) {

		Session session = HibernateLogManager.getSession();
		Criteria criteria = session.createCriteria(clazz);
		// 参数设置
		Set<String> keys = parameters.keySet();
		Object value;
		for (String key : keys) {
			value = parameters.get(key);
			if (key != null && value != null && value.toString().length() > 0) {
				criteria.add(Restrictions.eq(key, value));
			}
		}

		ProjectionList projection = Projections.projectionList();
		projection.add(Projections.count("eventId"));

		criteria.setProjection(projection);
		
		return (Long) criteria.uniqueResult();
	}

	/**
	 * 删除对应的LOG记录
	 * 
	 * @param clazz
	 *            操作的实体类
	 * @param parameters
	 *            参数值
	 */
	private static int delete(Class<? extends BasicLogModel> clazz,
			HashMap<String, Object> parameters) {
		Session session = HibernateLogManager.getSession();
		StringBuffer sql = new StringBuffer();
		sql.append("delete from ").append(clazz.getName()).append(
				" log where 1=1 ");

		// 设置HQL语句
		// 参数设置
		Set<String> keys = parameters.keySet();
		Object value;
		for (String key : keys) {
			value = parameters.get(key);
			if (key != null && value != null && value.toString().length() > 0) {
				sql.append(" and ").append("log.").append(key).append(" = :")
						.append(key.replace(".", "_"));
			}
		}

		Query query = session.createQuery(sql.toString());

		// 设置参数值
		// 参数设置
		for (String key : keys) {
			value = parameters.get(key);
			if (key != null && value != null && value.toString().length() > 0) {
				query.setParameter(key, value);
			}
		}

		return query.executeUpdate();
	}

	/**
	 * 查找符合条件的用户登录LOG的记录<br>
	 * 表达式的条件使用or关系
	 * 
	 * @param <T>
	 *            范型
	 * @param clazz
	 *            操作的实体类
	 * @param parameters
	 *            参数值
	 * @param firstResult
	 *            查找的开始偏移位置
	 * @param maxResults
	 *            查找的最大记录条数
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T extends BasicLogModel> List<T> loadOrExpression(
			Class<T> clazz, HashMap<String, Object> parameters,
			int firstResult, int maxResults, String order) {
		Session session = HibernateLogManager.getSession();
		StringBuffer sql = new StringBuffer();
		sql.append("from ").append(clazz.getName()).append(" log where 1=1 ");

		// 设置HQL语句
		// 参数设置
		StringBuffer orSql = new StringBuffer();
		Set<String> keys = parameters.keySet();
		Object value;
		for (String key : keys) {
			value = parameters.get(key);
			if (key != null && value != null && value.toString().length() > 0) {
				orSql.append(" or ").append(key).append(" = :").append(
						key.replace(".", "_"));
			}
		}

		if (orSql.length() > 1) {
			orSql.append(" )");
			sql.append(" and ( 1 = 2 ").append(orSql);
		}

		// 按排序
		if (order != null && order.length() > 0) {
			sql.append(" order by " + order + " asc ");
		}

		Query query = session.createQuery(sql.toString());

		// 设置参数值
		// 参数设置
		for (String key : keys) {
			value = parameters.get(key);
			if (key != null && value != null && value.toString().length() > 0) {
				query.setParameter(key.replace(".", "_"), value);
			}
		}

		if (firstResult >= 0) {
			query.setFirstResult(firstResult);
		}

		if (maxResults >= 0) {
			query.setMaxResults(maxResults);
		}

		return query.list();
	}

	/**
	 * 查找符合条件的用户登录LOG的记录数量<br>
	 * 表达式的条件使用or关系
	 * 
	 * @param clazz
	 *            操作的实体类
	 * @param parameters
	 *            参数
	 * @param beginTime
	 *            开始时间
	 * @param endTime
	 *            结束时间
	 * @return
	 */
	public static int getCountOrExpression(
			Class<? extends BasicLogModel> clazz,
			HashMap<String, Object> parameters) {
		Session session = HibernateLogManager.getSession();
		StringBuffer sql = new StringBuffer();
		sql.append("select count(*) from ").append(clazz.getName()).append(
				" log where 1=1 ");

		// 设置HQL语句
		// 参数设置
		StringBuffer orSql = new StringBuffer();
		Set<String> keys = parameters.keySet();
		Object value;
		for (String key : keys) {
			value = parameters.get(key);
			if (key != null && value != null && value.toString().length() > 0) {
				orSql.append(" or ").append(key).append(" = :").append(
						key.replace(".", "_"));
			}
		}

		Query query = session.createQuery(sql.toString());

		// 设置参数值
		// 参数设置
		for (String key : keys) {
			value = parameters.get(key);
			if (key != null && value != null && value.toString().length() > 0) {
				query.setParameter(key.replace(".", "_"), value);
			}
		}

		query.setMaxResults(1);

		return (Integer) query.uniqueResult();
	}

	/**
	 * 儲存金錢異動 log
	 * 
	 * @param player
	 * @param changeWay
	 * @param orderId
	 * @param goldChangeValue
	 * @param goldBeforeChange
	 * @param goldAfterChange
	 * @param module
	 *            執行寫 log 的 module 實體
	 */
	public static void savePlayerMoneyChangeLog(Player player, String gameId, String gameName, String gameHallId,
			String gameHallName, MoneyChangeWay changeWay, GUID orderId, BigDecimal goldChangeValue,
			BigDecimal goldBeforeChange, BigDecimal goldAfterChange, BasicServiceModule module) {
		if (player == null) {
			if (log.isErrorEnabled()) {
				log.error(GameUtility.getCurMethodName() + "() fail, player=null");
			}
			return;
		}

		AgentData agentData = player.getAgentDataInstance();

		PlayerMoneyChangeLogModel moneyChangeLog = new PlayerMoneyChangeLogModel();
		moneyChangeLog.setOrderId(orderId.toString());
		moneyChangeLog.setAccountId(player.getAccountId().toString());
		moneyChangeLog.setPlayerId(player.getGuid().toString());
		moneyChangeLog.setPlayerName(player.getNameWithNumber());
		moneyChangeLog.setUserType(player.getUserType());
		moneyChangeLog.setGameId(gameId);
		moneyChangeLog.setGameName(gameName);
		moneyChangeLog.setGameHallId(gameHallId);
		moneyChangeLog.setGameHallName(gameHallName);
		moneyChangeLog.setChangeWay(changeWay.getId());
		moneyChangeLog.setChangeWayDesc(changeWay.getDesc());
		moneyChangeLog.setVenderId(agentData.getVenderId());
		moneyChangeLog.setSubVenderId(agentData.getSubVenderId());
		moneyChangeLog.setGoldChangeValue(goldChangeValue);
		moneyChangeLog.setGoldBeforeChange(goldBeforeChange);
		moneyChangeLog.setGoldAfterChange(goldAfterChange);
		module.saveDbLog(moneyChangeLog);
	}

	/**
	 * 儲存暫存錢包 log
	 * 
	 * @param orderId
	 * @param accountId
	 * @param playerId
	 * @param openId
	 * @param playerName
	 * @param gameId
	 * @param gameHallId
	 * @param coinType
	 * @param tmpChangeValue
	 * @param tmpBeforeChange
	 * @param tmpAfterChange
	 * @param goldChangeValue
	 * @param goldBeforeChange
	 * @param goldAfterChange
	 * @param changeWay
	 * @param venderId
	 * @param subVenderId
	 * @param module
	 */
	public static void saveTmpCashChangeLog(GUID orderId, String accountId, String playerId, String openId,
			String playerName, String gameId, String gameHallId, String coinType, BigDecimal tmpChangeValue,
			BigDecimal tmpBeforeChange, BigDecimal tmpAfterChange, BigDecimal goldChangeValue,
			BigDecimal goldBeforeChange, BigDecimal goldAfterChange, TmpCashChangeWay changeWay, String venderId,
			String subVenderId, BasicServiceModule module) {
		// 寫 log
		PlayerTmpCashChangeLogModel log = new PlayerTmpCashChangeLogModel();
		log.setOrderId(orderId.toString());
		log.setAccountId(accountId);
		log.setPlayerId(playerId);
		log.setOpenId(openId);
		log.setPlayerName(playerName);
		log.setGameId(gameId);
		log.setGameHallId(gameHallId);
		log.setCoinType(coinType);
		log.setTmpChangeValue(tmpChangeValue);
		log.setTmpBeforeChange(tmpBeforeChange);
		log.setTmpAfterChange(tmpAfterChange);
		log.setGoldChangeValue(goldChangeValue);
		log.setGoldBeforeChange(goldBeforeChange);
		log.setGoldAfterChange(goldAfterChange);
		log.setChangeWay(changeWay.getId());
		log.setChangeWayDesc(changeWay.name());
		log.setVenderId(venderId);
		log.setSubVenderId(subVenderId);

		module.saveDbLog(log);
	}

	/**
	 * 儲存暫存錢包 log
	 * 
	 * @param orderId
	 * @param accountId
	 * @param playerId
	 * @param openId
	 * @param playerName
	 * @param gameId
	 * @param gameHallId
	 * @param coinType
	 * @param tmpChangeValue
	 * @param tmpBeforeChange
	 * @param tmpAfterChange
	 * @param goldChangeValue
	 * @param goldBeforeChange
	 * @param goldAfterChange
	 * @param changeWay
	 * @param venderId
	 * @param subVenderId
	 * @param module
	 */
	public static void saveOpenScoreLog(GUID orderId, String accountId, String playerId, String openId,
			String playerName, String gameId, String gameHallId, String coinType, BigDecimal tmpChangeValue,
			BigDecimal tmpBeforeChange, BigDecimal tmpAfterChange, BigDecimal goldChangeValue,
			BigDecimal goldBeforeChange, BigDecimal goldAfterChange, BigDecimal totalChangeValue,
			BigDecimal totalBeforeChange, BigDecimal totalAfterChange, OpenScoreChangeWay changeWay, String venderId,
			String subVenderId, BasicServiceModule module) {
		// 寫 log
		OpenScoreLogModel log = new OpenScoreLogModel();
		log.setOrderId(orderId.toString());
		log.setAccountId(accountId);
		log.setPlayerId(playerId);
		log.setOpenId(openId);
		log.setPlayerName(playerName);
		log.setGameId(gameId);
		log.setGameHallId(gameHallId);
		log.setCoinType(coinType);
		log.setTmpChangeValue(tmpChangeValue);
		log.setTmpBeforeChange(tmpBeforeChange);
		log.setTmpAfterChange(tmpAfterChange);
		log.setGoldChangeValue(goldChangeValue);
		log.setGoldBeforeChange(goldBeforeChange);
		log.setGoldAfterChange(goldAfterChange);
		log.setTotalChangeValue(totalChangeValue);
		log.setTotalBeforeChange(totalBeforeChange);
		log.setTotalAfterChange(totalAfterChange);
		log.setChangeWay(changeWay.getId());
		log.setChangeWayDesc(changeWay.name());
		log.setVenderId(venderId);
		log.setSubVenderId(subVenderId);

		module.saveDbLog(log);
	}
}
